Skip to content

Fix implode losing non-empty-string when ConstantArrayType has all-optional keys#5578

Merged
VincentLanglet merged 3 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-a4hrrrw
May 2, 2026
Merged

Fix implode losing non-empty-string when ConstantArrayType has all-optional keys#5578
VincentLanglet merged 3 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-a4hrrrw

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Summary

  • Fix ImplodeFunctionReturnTypeExtension::inferConstantType() to respect isIterableAtLeastOnce() when enumerating optional-key subsets of a ConstantArrayType
  • When all keys are optional (e.g. from union-typed key expressions in loops) but the array is guaranteed non-empty, filter out the empty-array partial to avoid producing '' as a possible result
  • Without this fix, the '' result generalizes to literal-string during loop iterations, which contaminates the union and causes non-empty-string / non-falsy-string to widen to plain string

Test plan

  • Added regression test tests/PHPStan/Analyser/nsrt/bug-14558.php with both playground scenarios from the issue
  • Verified test fails without the fix and passes with it
  • make tests passes (11,974 tests, 79,546 assertions)
  • make phpstan passes (no errors)
  • make cs-fix passes (no violations)
  • Checked analogous extensions (ArraySum, ArrayMap, ArrayFilter, ArrayChangeKeyCase, Replace, ArrayColumn, Count) — none are affected because they don't enumerate optional-key combinations

Closes phpstan/phpstan#14558

…tional keys

When a ConstantArrayType has all-optional keys (e.g. from union-typed
key expressions in loops), ImplodeFunctionReturnTypeExtension's
inferConstantType() enumerated every optional-key subset including the
empty array. This produced '' as a possible implode result, which
generalized to literal-string and lost the non-empty-string guarantee.

Pass the isIterableAtLeastOnce() result into inferConstantType() and
filter out the empty-array partial when the array is guaranteed
non-empty.

Closes phpstan/phpstan#14558
Comment thread src/Type/Php/ImplodeFunctionReturnTypeExtension.php Outdated
Instead of a separate array_filter step before the loop, skip empty
partials directly inside the foreach that builds ConstantStringType
values. This is simpler and avoids the extra array_filter/array_values
calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread src/Type/Php/ImplodeFunctionReturnTypeExtension.php Outdated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@VincentLanglet VincentLanglet requested a review from staabm May 1, 2026 18:15
@VincentLanglet VincentLanglet merged commit 697e042 into phpstan:2.1.x May 2, 2026
658 of 661 checks passed
@VincentLanglet VincentLanglet deleted the create-pull-request/patch-a4hrrrw branch May 2, 2026 07:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants